#include <iostream>
#include <string.h>

/*
c++ 三法则
如果需要析构函数，则一定需要拷贝构造函数，和拷贝赋值函数。
c++五法则：
    为了支持移动语义，又增加了移动构造函数和移动赋值函数
    std::move 转化成右值(转化为临时对象,从变量中窃取资源)
*/
class String 
{
public:
    String() = default;

    String(const char* string)
    {
       std::cout << "created !" << std::endl;
       m_Size = strlen(string);
       m_Data = new char[m_Size + 1];
       memcpy(m_Data,string,m_Size);
       m_Data[m_Size] = 0;
    }   

    String(const String& other) //拷贝构造
      : m_Size(other.m_Size) 
    {
       std::cout << "copied !" << std::endl;
       m_Data = new char[m_Size + 1];
       memcpy(m_Data,other.m_Data,m_Size + 1);
    }   

    String(String&& other) //移动构造
    {
       std::cout << "moved!" << std::endl;
       m_Size = other.m_Size;
       m_Data = other.m_Data;

       other.m_Size = 0;
       other.m_Data = nullptr;
    }

 
    String& operator=(String &&other) noexcept // 移动赋值
    {
       std::cout << "assign moved!" << std::endl;

       if(this != &other ) //防止自赋值。导致数据丢失
       {
          delete[] m_Data;
          m_Size = other.m_Size;
          m_Data = other.m_Data;

          other.m_Size = 0;
          other.m_Data = nullptr;      
       }
        return *this;
    } 

    //拷贝赋值
    String& operator=(String &other) noexcept
    {
       std::cout << "assign copied!" << std::endl;

       if(this != &other ) //防止自赋值。导致数据丢失
       {
          delete[] m_Data; // 释放旧内存
          m_Size = other.m_Size;
          m_Data = new char[m_Size];
          memcpy(m_Data,other.m_Data,m_Size);   
       }
        return *this;
    }

    ~String()
    {
      printf("Destoryed!\n");
      delete[] m_Data;
    }

    void print()
    {
      for(int32_t i = 0; i < m_Size; i++ )
      {
        printf("%c",m_Data[i]);
      }

      printf("\n");
    }

    friend std::ostream& operator<<(std::ostream& stream,const String& string);

private:
    char* m_Data;
    int32_t m_Size;
};

class Entity
{
   public:
     Entity(const String& name) :
      m_Name(name)
     {
      
     }
  
     Entity(String&& name) :
      m_Name(std::move(name))
     // m_Name( (String&&)name) 
     {
      
     }

    void PrintName()
    {
        m_Name.print();
    }

    private:
        String m_Name;

};


std::ostream& operator<<(std::ostream& stream,const String& string)
{
     stream << string.m_Data;
     return stream;
}

int main()
{
  // Entity entity("Cheron");//传入String对象（使用move语义）
  // entity.PrintName();


//  String str = "hello";
//  String dest = std::move(str);// 类型写在变量前面（进行对象构造）

  //移动赋值 （把一个变量赋值到一个已有的变量） 
   String apple = "apple";
   String dest;

   dest = apple; //拷贝赋值
   std::cout << "apple: " ;
   apple.print();
   std::cout << "dest: " ;
   dest.print();
  
   dest = std::move(apple);
   //dest.operator=(std::move(apple));
   std::cout << "apple: " ;
   apple.print();
   std::cout << "dest: " ;
   dest.print();

  //std::cin.get();
}